import chisel3._
import chisel3.util._

// 数据Cache顶层模块，参数化：SIZE（组相数），LINE_SIZE（cache行字节数），WAY_NUM（组路数），UseLRU（是否使用LRU替换）
class MyDCache(val SIZE: Int, val LINE_SIZE: Int, val WAY_NUM: Int, val UseLRU: Boolean)
    extends Module {
  // ============ 常用Width定义 ===========
  val INDEX_WIDTH   = log2Ceil(SIZE)             // set数量，决定index位宽
  val OFFSET_WIDTH  = log2Ceil(LINE_SIZE)        // 行内偏移，用于address
  val WAY_NUM_WIDTH = log2Ceil(WAY_NUM)          // 路数bit宽
  val LINE_BIT_SIZE = LINE_SIZE * 8              // 每行bit总数
  val LINE_WORD_NUM = LINE_SIZE / 4              // 每行有多少32bit数据
  // 打印参数便于调试
  println("Data Cache Size: " + SIZE)
  println("Data Cache Line Size   : " + LINE_WORD_NUM + " Word | " + LINE_SIZE + " Byte | " + LINE_BIT_SIZE + " Bit")
  println("Data Cache Way Number  : " + WAY_NUM)
  // 强制检查index+offset不能太大（比如csrs地址位宽）
  assert(
    (INDEX_WIDTH + OFFSET_WIDTH <= 12).asBool,
    "Index width + offset width should be <= 12, but given is %d\n",
    (INDEX_WIDTH + OFFSET_WIDTH).asUInt
  )

  // ============ 外部接口(io)定义 ===========
  val io = IO(new Bundle {
    // cpu端接口(请求)
    val valid     = Input(Vec(2,Bool()))        // 有效请求
    val op        = Input(Vec(2,Bool()))        // 读/写操作
    val tag       = Input(Vec(2,UInt(20.W)))   // tag部分
    val index     = Input(Vec(2,UInt(INDEX_WIDTH.W))) // 组索引
    val offset    = Input(Vec(2,UInt(OFFSET_WIDTH.W)))// 行内偏移
    val size      = Input(Vec(2,UInt(2.W)))     // 访问大小(b/h/w)
    val wstrb     = Input(Vec(2,UInt(4.W)))     // 写掩码
    val wdata     = Input(Vec(2,UInt(32.W)))    // 写数据
    val addr_ok   = Output(Vec(2,Bool()))     // 地址已被接受
    val data_ok   = Output(Vec(2,Bool()))       // 数据交互完成
    val rdata     = Output(Vec(2,UInt(32.W)))   // 读返回数据
    val uncached  = Input(Vec(2,Bool()))        // 直连方式访问标记

    val cacop_en         = Input(Vec(2,Bool()))           // cache操作命令(enable)
    val cacop_op         = Input(Vec(2,UInt(2.W)))        // cache操作类型
    val tlb_excp_cancel_req   = Input(Bool())      // 地址翻译异常取消本次请求

    // AXI接口（与内存子系统交互）
    val rd_req      = Output(Bool())               // 读请求发出
    val rd_type     = Output(UInt(3.W))            // 读类型
    val rd_addr     = Output(UInt(32.W))           // 读地址
    val rd_rdy      = Input(Bool())                // 可接受读请求
    val ret_valid   = Input(Bool())                // 返回数据有效
    val ret_last    = Input(Bool())                // 传输结束
    val ret_data    = Input(UInt(32.W))            // 读返回的数据
    val wr_req      = Output(Bool())               // 写请求发出
    val wr_type     = Output(UInt(3.W))            // 写类型
    val wr_addr     = Output(UInt(32.W))           // 写地址
    val wr_wstrb    = Output(UInt(4.W))            // 写掩码
    val wr_data     = Output(UInt(LINE_BIT_SIZE.W))// 写数据
    val wr_rdy      = Input(Bool())                // 可接受写请求

    // // to perf_counter
    // val cache_miss       = Output(Bool())

  })
  
  // ========== 计数器统计 ===========
  val total_req_counter   = RegInit(0.U(32.W))     // 总请求数
  val total_miss_counter  = RegInit(0.U(32.W))     // 总miss数
  val dcache_counter      = RegInit(0.U(32.W))     // 单独自增计数
  dcache_counter := dcache_counter + 1.U
  
  // ========== 标志与存储结构 ===========
  // 脏数据表：每个set/way都有一位
  val Dirty = RegInit(VecInit(Seq.fill(SIZE)(VecInit(Seq.fill(WAY_NUM)(false.B)))))
  // 数据RAM和Tag RAM实例化，均为多路组相联结构（每组WAY_NUM组ram）
  val DataBank  = Array.fill(WAY_NUM)(Module(new DataRAM(SIZE, LINE_BIT_SIZE)).io) // data存储
  val TagvBank  = Array.fill(WAY_NUM)(Module(new TagvRAM(SIZE, 20)).io)            // Tag+valid位
  // 有效位寄存器
  val Valid     = RegInit(VecInit(Seq.fill(SIZE)(0.U(WAY_NUM.W))))                 // 各组每路的valid

  // ========== 命中判断 ===========
  val way_hit         = Wire(Vec(2,Vec(WAY_NUM, Bool())))            // 每路是否命中
  val cache_hit       = Wire(Vec(2,Bool()))                          // 是否有命中
  val cache_hit_way   = Wire(Vec(2,UInt(WAY_NUM_WIDTH.W)))           // 命中的是哪一路

  // ========== 替换路相关 ==========
  val replaced_way_buffer     = RegInit(VecInit(Seq.fill(2)(0.U(WAY_NUM_WIDTH.W)))) // 选择被替换的路（写回/替换写入）
  val replaced_index_buffer   = RegInit(VecInit(Seq.fill(2)(0.U(INDEX_WIDTH.W))))   // 被替换的组
  val replaced_way            = Wire(Vec(2,UInt(WAY_NUM_WIDTH.W)))  
  val replaced_data           = Wire(Vec(2,UInt(LINE_BIT_SIZE.W)))
  val replaced_tag            = Wire(Vec(2,UInt(20.W)))
  val replaced_index          = Wire(Vec(2,UInt(INDEX_WIDTH.W)))
  val replaced_addr           = Wire(Vec(2,UInt(32.W)))
  val replaced_dirty          = Wire(Vec(2,Bool()))
  val replaced_valid          = Wire(Vec(2,Bool()))

  val need_write_axi      = RegInit(VecInit(Seq.fill(2)(false.B)))  // 是否需要向AXI写（写回内存）
  val need_read_axi       = RegInit(VecInit(Seq.fill(2)(false.B)))   // 是否需要向AXI读（装填miss）

  // ========== 读/写数据通道相关 ===========
  val read_data           = Wire(Vec(WAY_NUM, UInt(LINE_BIT_SIZE.W)))      // 从所有路读出的一行数据
  val target_data0        = Wire(Vec(LINE_WORD_NUM, UInt(32.W)))
  val target_data1        = Wire(Vec(LINE_WORD_NUM, UInt(32.W)))            // 某行按word组织后的数据
  val read_tagv           = Wire(Vec(WAY_NUM, UInt(21.W)))                   // tag+valid
  val read_tag            = Wire(Vec(WAY_NUM, UInt(20.W)))
  val read_valid          = Wire(Vec(WAY_NUM, Bool()))

  // ========== 各种请求状态/缓冲 ==========
  val receive_request     = Wire(Vec(2,Bool()))     // 是否接收新请求
  val uncached_write      = Wire(Vec(2,Bool()))     // 是否为直连写
  val uncached_read       = Wire(Vec(2,Bool()))
  val uncached_en         = Wire(Vec(2,Bool()))
  val read_hit            = Wire(Vec(2,Bool()))     // 是否读命中
  val write_hit           = Wire(Vec(2,Bool()))     // 是否写命中
  val cache_unbussy       = Wire(Vec(2,Bool()))     // cache是否空闲可接收请求

  // ========== AXI仲裁 ==========
  val rd_arb     = Module(new Arbiter(Bool(), 2))
  val rd_req_vec = Wire(Vec(2, Bool()))
  val wr_req_vec = Wire(Vec(2, Bool()))

  // ========== Cache状态机 ============
  object CacheState extends ChiselEnum {
    val IDLE, LOOKUP, WRITEHIT, MISS, REPLACE, REFILL, RESPOND = Value
  }
    // 补充注释：定义cache行为状态机（空闲、查找、写hit、miss、替换、填充、响应）
    //val correct_annotation_map = Map[String, UInt](
      //"IDLE" -> 0.U,
      //"LOOKUP" -> 1.U,
     // "WRITEHIT" -> 2.U,
     // "MISS" -> 3.U,
     /// "REPLACE" -> 4.U,
    //  "REFILL" -> 5.U,
    //  "RESPOND" -> 6.U
   // )
  //}
  val main_state  = RegInit(VecInit(Seq.fill(2)(CacheState.IDLE)))

  // 状态机便捷信号
  val is_idle     = Wire(Vec(2, Bool()))
  val is_lookup   = Wire(Vec(2, Bool()))
  val is_writehit = Wire(Vec(2, Bool()))
  val is_miss     = Wire(Vec(2, Bool()))
  val is_replace  = Wire(Vec(2, Bool()))
  val is_refill   = Wire(Vec(2, Bool()))
  val is_respond  = Wire(Vec(2, Bool()))

  for (i <- 0 until 2) {
    is_idle(i)     := main_state(i) === CacheState.IDLE
    is_lookup(i)   := main_state(i) === CacheState.LOOKUP
    is_writehit(i) := main_state(i) === CacheState.WRITEHIT
    is_miss(i)     := main_state(i) === CacheState.MISS
    is_replace(i)  := main_state(i) === CacheState.REPLACE
    is_refill(i)   := main_state(i) === CacheState.REFILL
    is_respond(i)  := main_state(i) === CacheState.RESPOND
  }

  // ========== AXI输出请求信号保持 ===========
  val rd_type_buffer    = RegInit(VecInit(Seq.fill(2)(0.U(3.W))))
  val rd_addr_buffer    = RegInit(VecInit(Seq.fill(2)(0.U(32.W))))
  val wr_type_buffer    = RegInit(VecInit(Seq.fill(2)(0.U(3.W))))
  val wr_addr_buffer    = RegInit(VecInit(Seq.fill(2)(0.U(32.W))))
  val wr_wstrb_buffer   = RegInit(VecInit(Seq.fill(2)(0.U(4.W))))
  val wr_data_buffer    = RegInit(VecInit(Seq.fill(2)(0.U(LINE_BIT_SIZE.W))))

  // ========== 请求缓冲器 ==========
  val request_cacop_en_buffer   = RegInit(VecInit(Seq.fill(2)(false.B)))
  val request_cacop_op_buffer   = RegInit(VecInit(Seq.fill(2)(0.U(2.W))))
  val request_op_buffer         = RegInit(VecInit(Seq.fill(2)(false.B)))
  val request_tag_buffer        = RegInit(VecInit(Seq.fill(2)(0.U(20.W))))
  val request_index_buffer      = RegInit(VecInit(Seq.fill(2)(0.U(INDEX_WIDTH.W))))
  val request_offset_buffer     = RegInit(VecInit(Seq.fill(2)(0.U(OFFSET_WIDTH.W))))
  val request_uncached_buffer   = RegInit(VecInit(Seq.fill(2)(false.B)))
  val target_word_id            = RegInit(VecInit(Seq.fill(2)(0.U((OFFSET_WIDTH-2).W))))     // 行内目标字
  val request_wdata_buffer      = RegInit(VecInit(Seq.fill(2)(0.U(32.W))))
  val request_wstrb_buffer      = RegInit(VecInit(Seq.fill(2)(0.U(4.W))))
  val request_size_buffer       = RegInit(VecInit(Seq.fill(2)(0.U(2.W))))

  val request_addr              = Wire(Vec(2,UInt(32.W)))
  val request_line_addr         = Wire(Vec(2,UInt(32.W)))
  val normal_request            = Wire(Vec(2,Bool()))

  for(i<-0 until 2){
    request_addr(i)          := Cat(Mux(is_lookup(i), io.tag(i), request_tag_buffer(i)), 
                                  request_index_buffer(i), request_offset_buffer(i))
    request_line_addr(i)     := Cat(Mux(is_lookup(i), io.tag(i), request_tag_buffer(i)),
                                   request_index_buffer(i), 0.U(OFFSET_WIDTH.W))
  }

  // miss后写入数据的数据临时缓冲(写缓存)
  //val ret_data_buffer0   = RegInit(VecInit.fill(LINE_WORD_NUM)(0.U(32.W)))
  //val ret_data_buffer1   = RegInit(VecInit.fill(LINE_WORD_NUM)(0.U(32.W)))
  val ret_data_buffer = RegInit(
      VecInit(Seq.fill(2)(VecInit(Seq.fill(LINE_WORD_NUM)(0.U(32.W)))))
) 
  val miss_data_ret_cnt = RegInit(VecInit(Seq.fill(2)(0.U((OFFSET_WIDTH - 2).W))))   // miss补全计数

  // ========== cacop指令处理 ==========
    val cacop_op_0 = Wire(Vec(2,Bool()))
    val cacop_op_1 = Wire(Vec(2,Bool()))
    val cacop_op_2 = Wire(Vec(2,Bool()))
    val cacop_way  = Wire(Vec(2,UInt(WAY_NUM_WIDTH.W)))
  for(i<-0 until 2){
    cacop_op_0(i)  := request_cacop_en_buffer(i) && request_cacop_op_buffer(i) === 0.U // 指定类型
    cacop_op_1(i)  := request_cacop_en_buffer(i) && request_cacop_op_buffer(i) === 1.U
    cacop_op_2(i)  := request_cacop_en_buffer(i) && request_cacop_op_buffer(i) === 2.U
    cacop_way(i)   := request_addr(i)(WAY_NUM_WIDTH-1, 0)
  
  }
  
  // 替换路选择规则
  for(i<-0 until 2){           
    replaced_way(i)    := Mux(cacop_op_2(i) && cache_hit(i), 
                            cache_hit_way(i), 
                            Mux(cacop_op_0(i) || cacop_op_1(i),
                              cacop_way(i), 
                              dcache_counter(WAY_NUM_WIDTH-1, 0) + i.U))          
    replaced_data(i)   := read_data(replaced_way(i))
    replaced_dirty(i)  := Dirty(replaced_index(i))(replaced_way(i))
    replaced_index(i)  := request_index_buffer(i)
    replaced_tag(i)    := read_tag(replaced_way(i))
    replaced_valid(i)  := read_valid(replaced_way(i))
    replaced_addr(i)   := Cat(replaced_tag(i), replaced_index(i), 0.U(OFFSET_WIDTH.W))
  }


  // 获取每路tag和valid信号
  for (i <- 0 until WAY_NUM) {
    read_tagv(i) := Cat(TagvBank(i).douta, Valid(request_index_buffer(0))) // 按实际需求选index
    read_tag(i)  := read_tagv(i)(20, 1)
    read_valid(i):= read_tagv(i)(0)
  }
  for (i <- 0 until WAY_NUM) {
    TagvBank(i).wea := false.B
    read_tag(i)   := read_tagv(i)(20, 1)
    read_valid(i) := read_tagv(i)(0)
  }
  // 判定命中
  for (i <- 0 until WAY_NUM) {
    way_hit(0)(i) := (read_tag(i) === io.tag(0)) && read_valid(i)
    way_hit(1)(i) := (read_tag(i) === io.tag(1)) && read_valid(i)
  }

  // 块内Word组织
  for(i<-0 until 2) {
    cache_hit(i)       := way_hit(i).reduce(_||_) && !io.tlb_excp_cancel_req
    cache_hit_way(i)   := OHToUInt(way_hit(i))
    uncached_en(i)     := Mux(is_lookup(i), io.uncached(i), 
                              request_uncached_buffer(i)) && !request_cacop_en_buffer(i)
    uncached_read(i)   := uncached_en(i) && !request_op_buffer(i)
    uncached_write(i)  := uncached_en(i) && request_op_buffer(i)
    normal_request(i)  := !Mux(is_lookup(i), io.uncached(i), 
                              request_uncached_buffer(i)) && !request_cacop_en_buffer(i)
    read_hit(i)        := cache_hit(i) && !request_op_buffer(i) && normal_request(i)
    write_hit(i)       := cache_hit(i) && request_op_buffer(i) && normal_request(i)
    cache_unbussy(i)   := is_idle(i) || (is_lookup(i) && cache_hit(i) && normal_request(i)) || 
                              is_respond(i) || is_replace(i) && !need_read_axi(i) 
    receive_request(i) := cache_unbussy(i) && (io.valid(i) || io.cacop_en(i))
    io.addr_ok(i)      := cache_unbussy(i)
    io.data_ok(i)      := is_lookup(i) && (cache_hit(i) || request_op_buffer(i)) && !uncached_en(i) || is_respond(i)
  
  }
  target_data0    := read_data(cache_hit_way(0)).asTypeOf(target_data0)
  target_data1    := read_data(cache_hit_way(1)).asTypeOf(target_data1)
  for (i <- 0 until 2) {
    io.rdata(i) := Mux(is_respond(i), 
                      ret_data_buffer(i)(target_word_id(i)), 
                      Mux(i.U === 0.U, target_data0(target_word_id(i)), target_data1(target_word_id(i))))
  }

  // ========== AXI接口输出 ===========                          
  for (i <- 0 until 2) {
    rd_req_vec(i) := is_replace(i) && need_read_axi(i)
    wr_req_vec(i) := is_miss(i) && need_write_axi(i)
  }

  rd_arb.io.in(0).valid := rd_req_vec(0)
  rd_arb.io.in(1).valid := rd_req_vec(1)
  rd_arb.io.in(0).bits  := true.B
  rd_arb.io.in(1).bits  := true.B

  val rd_grant    = rd_arb.io.out.valid && rd_arb.io.out.bits
  val rd_port_sel = rd_arb.io.chosen

  io.rd_req  := rd_arb.io.out.valid
  io.rd_type := Mux(rd_port_sel, rd_type_buffer(1), rd_type_buffer(0))
  io.rd_addr := Mux(rd_port_sel, rd_addr_buffer(1), rd_addr_buffer(0))

  val wr_arb = Module(new Arbiter(Bool(), 2))
  wr_arb.io.in(0).valid := wr_req_vec(0)
  wr_arb.io.in(1).valid := wr_req_vec(1)
  wr_arb.io.in(0).bits  := true.B
  wr_arb.io.in(1).bits  := true.B

  val wr_grant    = wr_arb.io.out.valid && wr_arb.io.out.bits
  val wr_port_sel = wr_arb.io.chosen

  io.wr_req   := wr_arb.io.out.valid
  io.wr_type  := Mux(wr_port_sel, wr_type_buffer(1), wr_type_buffer(0))
  io.wr_addr  := Mux(wr_port_sel, wr_addr_buffer(1), wr_addr_buffer(0))
  io.wr_wstrb := Mux(wr_port_sel, wr_wstrb_buffer(1), wr_wstrb_buffer(0))
  io.wr_data  := Mux(wr_port_sel, wr_data_buffer(1), wr_data_buffer(0))


  // ========== 数据合并、写入处理 ===========  //将32位分为4个字节
  for (i <- 0 until 2) {
    val ret_data_v = io.ret_data.asTypeOf(Vec(4, UInt(8.W)))
    val target_data_v = Mux(i.U === 0.U, 
                           target_data0(target_word_id(0)).asTypeOf(Vec(4, UInt(8.W))),
                           target_data1(target_word_id(1)).asTypeOf(Vec(4, UInt(8.W))))
    val request_wdata_v = request_wdata_buffer(i).asTypeOf(Vec(4, UInt(8.W)))
    
    val merged_data = Wire(Vec(4, UInt(8.W)))
    for (j <- 0 until 4) {
      merged_data(j) := Mux(request_wstrb_buffer(i)(j), request_wdata_v(j), ret_data_v(j))
    }
    
    when(is_refill(i) && io.ret_valid) {
      ret_data_buffer(i)(miss_data_ret_cnt(i)) := merged_data.asUInt
    }
  }

  // ========== 处理对端写读端口访问冲突 ===========
  //val conflict      = Wire(Vec(WAY_NUM, Bool()))
 // val conflict_flag = RegInit(VecInit.fill(WAY_NUM)(false.B))
  val conflict_data = RegInit(VecInit.fill(WAY_NUM)(0.U(LINE_BIT_SIZE.W)))
  // val bank_conflict = request_index_buffer(0) === request_index_buffer(1)

    /// DataBank(i).wea     := is_lookup && write_hit && way_hit(i) || is_respond && normal_request && (i.asUInt === replaced_way_buffer)
  for (p <- 0 until 2) {
    for (i <- 0 until WAY_NUM) {
      DataBank(i).clka  := clock
      DataBank(i).clkb  := clock
      // 写端口A：命中写或替换写
      DataBank(i).addra := Mux(write_hit(p) && way_hit(p)(i), 
                              request_index_buffer(p),
                              replaced_index_buffer(p))
     DataBank(i).dina := Mux(is_lookup(p), 
                            Mux(p.U === 0.U, target_data0.asUInt, 
                                target_data1.asUInt), 
                            ret_data_buffer(p).asUInt)
      DataBank(i).wea   := is_lookup(p) && write_hit(p) && way_hit(p)(i) ||
                           is_respond(p) && normal_request(p) && (i.U === replaced_way_buffer(p))
      // 读端口B：正常读
      DataBank(i).addrb := io.index(p)
      read_data(i)      := DataBank(i).doutb
    
      // bank写冲突
       when((request_index_buffer(0) === io.index(p) || request_index_buffer(1) === io.index(p)) && DataBank(i).wea) {
        conflict_data(i) := DataBank(i).dina
      }.otherwise {
        conflict_data(i) := 0.U
      }
    }                           
  }

  // ========== Tag和Valid写入控制 ===========
 //val valid_in = Wire(Vec(WAY_NUM, UInt(1.W)))
  //for (p <- 0 until 2) {
    //for (i <- 0 until WAY_NUM) {
      // TagvBank端口独立写入
     // read_tagv(i)      := Cat(TagvBank(i).douta,Valid(request_index_buffer(p)))
     // TagvBank(i).clka  := clock
     // TagvBank(i).addra := Mux(receive_request(p), io.index(p), request_index_buffer(p))
     // TagvBank(i).dina  := Mux(request_cacop_en_buffer(p), 0.U(20.W), request_tag_buffer(p))
      // 写使能：miss且选中路或cacop
     // TagvBank(i).wea   := is_miss(p) && !uncached_en(p) && 
     //                       ((i.U === replaced_way_buffer(p)) || request_cacop_en_buffer(p)) &&
                    
      // 有效位写入
    //  valid_in(p)(i)    := Mux(TagvBank(i).wea, !request_cacop_en_buffer(p), Valid(request_index_buffer(p))(i))
    //}
    // 写入Valid
    //Valid(request_index_buffer(p)) := valid_in(p).asUInt
  //}
  // ====================== 主状态机流程 ======================
  for (i <- 0 until 2) {
    switch(main_state(i)) {
      is(CacheState.IDLE) {// 空闲态，等待新请求
        when(receive_request(i)) {
          // 接收请求，所有信息写入buffer，准备下一周期查找
          request_cacop_en_buffer(i) := io.cacop_en(i)
          request_cacop_op_buffer(i) := io.cacop_op(i)
          request_op_buffer(i)       := io.op(i)
          request_tag_buffer(i)      := io.tag(i)
          request_index_buffer(i)    := io.index(i)
          request_offset_buffer(i)   := io.offset(i)
          request_size_buffer(i)     := io.size(i)
          request_wstrb_buffer(i)    := io.wstrb(i)
          request_wdata_buffer(i)    := io.wdata(i)
          target_word_id(i)          := io.offset(i)(OFFSET_WIDTH-1, 2)
          main_state(i)              := CacheState.LOOKUP
        }
      }
      is(CacheState.LOOKUP) { // 查找阶段
        total_req_counter := total_req_counter + 1.U
        request_uncached_buffer(i) := io.uncached(i)

        when(io.tlb_excp_cancel_req) {
          main_state(i) := CacheState.IDLE
        }.elsewhen(!cache_hit(i) || request_cacop_en_buffer(i) || uncached_en(i)) {
          // miss 或cache操作类请求 或uncached
          when(uncached_en(i)) { target_word_id(i) := 0.U }
          replaced_way_buffer(i)   := replaced_way(i)
          replaced_index_buffer(i) := replaced_index(i)
          need_write_axi(i)        := (cacop_op_2(i) && cache_hit(i) || cacop_op_1(i) || cacop_op_0(i) || normal_request(i)) && 
                                      replaced_dirty(i) && replaced_valid(i) || uncached_write(i)
          // 缓冲AXI请求信息
          rd_type_buffer(i)  := Mux(uncached_en(i), Cat(0.U(1.W), request_size_buffer(i)), "b100".U)
          rd_addr_buffer(i)  := Mux(uncached_en(i), request_addr(i), request_line_addr(i))
          wr_type_buffer(i)  := Mux(uncached_en(i), Cat(0.U(1.W), request_size_buffer(i)), "b100".U)
          wr_addr_buffer(i)  := Mux(uncached_en(i), request_addr(i), replaced_addr(i))
          wr_data_buffer(i)  := Mux(uncached_en(i), request_wdata_buffer(i), replaced_data(i))
          wr_wstrb_buffer(i) := Mux(uncached_en(i), request_wstrb_buffer(i), "b1111".U)
          main_state(i) := Mux(cacop_op_2(i) && !cache_hit(i), CacheState.IDLE, CacheState.MISS) 
          total_miss_counter := total_miss_counter + 1.U
        }.elsewhen(receive_request(i)) {
          // 连续命中时提前接收新请求
          request_cacop_en_buffer(i) := io.cacop_en(i)
          request_cacop_op_buffer(i) := io.cacop_op(i)
          request_op_buffer(i)       := io.op(i)
          request_tag_buffer(i)      := io.tag(i)
          request_index_buffer(i)    := io.index(i)
          request_offset_buffer(i)   := io.offset(i)
          request_size_buffer(i)     := io.size(i)
          request_wstrb_buffer(i)    := io.wstrb(i)
          request_wdata_buffer(i)    := io.wdata(i)
          target_word_id(i)          := io.offset(i)(OFFSET_WIDTH-1, 2)
          main_state(i) := CacheState.LOOKUP
        } .otherwise {
          main_state(i) := CacheState.IDLE
        }
        when(write_hit(i))  {
          Dirty(request_index_buffer(i))(cache_hit_way(i)) := true.B
        }
      }
      is(CacheState.MISS) {
        // Miss阶段，决定是否先写回再装填
        when(io.wr_rdy || !need_write_axi(i)) {
          need_read_axi(i) := uncached_read(i) || normal_request(i)
          main_state(i) := CacheState.REPLACE
        }
      }
      is(CacheState.REPLACE) {
        when(need_read_axi(i)) {
          // 等待读端内存准备
          when(io.rd_rdy) { 
            main_state(i) := CacheState.REFILL
            miss_data_ret_cnt(i) := 0.U
            ret_data_buffer(i)   := (0.U).asTypeOf(ret_data_buffer(i))
          }
        }.otherwise { // 换下一请求
          when(receive_request(i)) {
            request_cacop_en_buffer(i) := io.cacop_en(i)
            request_cacop_op_buffer(i) := io.cacop_op(i)
            request_op_buffer(i)       := io.op(i)
            request_tag_buffer(i)      := io.tag(i)
            request_index_buffer(i)    := io.index(i)
            request_offset_buffer(i)   := io.offset(i)
            request_size_buffer(i)     := io.size(i)
            request_wstrb_buffer(i)    := io.wstrb(i)
            request_wdata_buffer(i)    := io.wdata(i)
            target_word_id(i)          := io.offset(i)(OFFSET_WIDTH-1, 2)
            main_state(i) := CacheState.LOOKUP
          }.otherwise {
            main_state(i) := CacheState.IDLE 
          }
        }
      }
      is(CacheState.REFILL) { 
        // Miss补全/行填充阶段
        when(io.ret_valid) {
          miss_data_ret_cnt(i) := miss_data_ret_cnt(i) + 1.U
          when(io.ret_last) {
            // 装填完毕，写数据有效性与脏位
           when(normal_request(i)) {
              Dirty(replaced_index_buffer(i))(replaced_way_buffer(i)) := request_op_buffer(i)
              Valid(replaced_index_buffer(i))(replaced_way_buffer(i)) := true.B
              TagvBank(replaced_way_buffer(i)).clka  := clock
              TagvBank(replaced_way_buffer(i)).addra := replaced_index_buffer(i)
              TagvBank(replaced_way_buffer(i)).dina  := request_tag_buffer(i)
              TagvBank(replaced_way_buffer(i)).wea   := true.B
            }
            // cacop特殊命令（清除等操作）
            when(request_cacop_en_buffer(i)) {
              TagvBank(cacop_way(i)).clka  := clock
              TagvBank(cacop_way(i)).addra := request_index_buffer(i)
              TagvBank(cacop_way(i)).dina  := 0.U(20.W)
              TagvBank(cacop_way(i)).wea   := true.B
              Valid(request_index_buffer(i))(cacop_way(i)) := false.B
              Dirty(request_index_buffer(i))(cacop_way(i)) := false.B
            }
            
            main_state(i) := CacheState.RESPOND
          }
        }
      }
      is(CacheState.RESPOND) { 
        // 返回响应
        when(receive_request(i)) {
          request_cacop_en_buffer(i) := io.cacop_en(i)
          request_cacop_op_buffer(i) := io.cacop_op(i)
          request_op_buffer(i)       := io.op(i)
          request_tag_buffer(i)      := io.tag(i)
          request_index_buffer(i)    := io.index(i)
          request_offset_buffer(i)   := io.offset(i)
          request_size_buffer(i)     := io.size(i)
          request_wstrb_buffer(i)    := io.wstrb(i)
          request_wdata_buffer(i)    := io.wdata(i)
          target_word_id(i)          := io.offset(i)(OFFSET_WIDTH-1, 2)
          main_state(i) := CacheState.LOOKUP
        }.otherwise {
          main_state(i) := CacheState.IDLE
        }
      }
    }
  }


  // // 周期性打印miss率
  // when(dcache_counter(15,0).asUInt===0.U)
  // {
  //   printf(cf"[DATA] cache miss rate: $total_miss_counter%d $total_req_counter%d\n")
  // }
}


// 简单的仲裁器实现
class Arbiter(typ: Data, n: Int) extends Module {
  val io = IO(new Bundle {
    val in = Flipped(Vec(n, Decoupled(typ)))
    val out = Decoupled(typ)
    val chosen = Output(UInt(log2Ceil(n).W))
  })
  
  // 简单的轮转仲裁
  val grantMask = RegInit(VecInit.tabulate(n)(i => (i == 0).B))
  val grantIdx = PriorityEncoder(grantMask.zip(io.in.map(_.valid)).map { case (m, v) => m && v })
  
  io.out.valid := io.in.map(_.valid).reduce(_||_)
  io.out.bits := Mux1H(io.in.zipWithIndex.map { case (in, i) => (i.U === grantIdx) -> in.bits })
  io.chosen := grantIdx
  
  for (i <- 0 until n) {
    io.in(i).ready := io.out.ready && (grantIdx === i.U)
  }
  
  when(io.out.fire()) {
    grantMask := VecInit((0 until n).map(i => (i == (grantIdx + 1) % n).B))
  }
}